package com.qianzhu8.kfc.boot.client;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.qianzhu8.kfc.boot.constant.HttpMethodConstants;
import com.qianzhu8.kfc.boot.props.KfcProperty;
import com.qianzhu8.kfc.boot.request.BaseRequest;
import com.qianzhu8.kfc.boot.response.BaseResponse;
import com.qianzhu8.kfc.boot.util.BeanUtils;
import com.qianzhu8.kfc.boot.util.SignUtils;
import com.qianzhu8.kfc.boot.util.UrlParamsUtils;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 执行客户端
 *
 * @author xuyanjun
 * @date 2020/4/10
 */
public class KfcExecuteClientImpl implements KfcExecuteClient {

    /**
     * 域名
     */
    private final KfcProperty kfcProperty;

    /**
     * construct
     *
     * @param kfcProperty kfcProperty
     */
    public KfcExecuteClientImpl(KfcProperty kfcProperty) {
        this.kfcProperty = kfcProperty;
    }

    /**
     * 执行请求
     *
     * @param request request
     * @return response
     */
    @Override
    public <T extends BaseResponse> T execute(BaseRequest<T> request) {
        prepareRequest(request);

        String url = kfcProperty.getServerUrl() + request.getAction();
        Map<String, Object> requestMap = buildRequestMap(request);

        String response;
        if (HttpMethodConstants.POST.equalsIgnoreCase(request.getMethod())) {
            response = HttpUtil.post(url, JSON.toJSONString(requestMap), kfcProperty.getTimeout());
        } else {
            final String params = UrlParamsUtils.toParams(requestMap);
            response = HttpUtil.get(url + "?" + params, kfcProperty.getTimeout());
        }

        return JSON.parseObject(response, request.getResponseClass());
    }

    /**
     * 准备请求，填充统一配置
     *
     * @param request request
     */
    private void prepareRequest(BaseRequest request) {
        request.setPlatformId(kfcProperty.getPlatformId())
                .setTimestamp(System.currentTimeMillis());

        Map<String, String> signMap = SignUtils.buildSignMap(request);
        String sign = SignUtils.generateSign(signMap, kfcProperty.getSecret());
        request.setSign(sign);
    }

    /**
     * 构建请求map
     *
     * @param request request
     * @return 请求map
     */
    @SneakyThrows
    private Map<String, Object> buildRequestMap(BaseRequest request) {
        boolean isPost = HttpMethodConstants.POST.equalsIgnoreCase(request.getMethod());

        List<Field> fields = BeanUtils.getAllFields(request.getClass());
        Map<String, Object> requestMap = new HashMap<>(8);
        for (Field field : fields) {
            field.setAccessible(true);
            final Object fieldValue = field.get(request);
            if ( fieldValue!= null) {
                requestMap.put(field.getName(), isPost ? fieldValue.toString() : URLEncoder.encode(fieldValue.toString(), "utf-8"));
            }
        }

        return requestMap;
    }
}
